package com.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.concurrent.TimeoutException;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android_serialport_api.SerialPort;

/**
 * 连接通信类
 *
 * @author 刘亚东
 *
 */
@SuppressLint("DefaultLocale")
@SuppressWarnings("unused")
public class Connection {
	// 接受设备传输数据流
	private InputStream inputStream = null;
	private OutputStream outputStream = null;
	private SerialPort serialPort = null;
	// 接收数据数组
	private byte[] bytesToRecv;
	private List<Byte> readlist = null;
	private int readlistTcount = 0;
	private long time = 0;

	public Connection() throws SecurityException, IOException {
		serialPort = new SerialPort(115200, 0);
		inputStream = serialPort.getInputStream();
		outputStream = serialPort.getOutputStream();
	}

	/**
	 * @param context
	 *            指令
	 * @return
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public String send(String context) throws IOException,
			InterruptedException, Exception {
		String content = "";
		try {
			outputStream.write(EncodingUtil.hex2byte(EncodingUtil
					.change(context)));

			time = System.currentTimeMillis() + 5000;
			int x = 0;
			// 55AA 07 0012 DFB9 0000 0000 0000 0000 0000 0000 0000 0000 00 73
			// 55AA 08 0002 DFBF 3B 51丢弃
			while (true) {

				if (System.currentTimeMillis() <= time) {
					x = inputStream.available(); // 预测缓存区数据长度
					if (x > 0) {
						bytesToRecv = new byte[1];
						inputStream.read(bytesToRecv);
						// 第一次
						if (readlist == null) {
							// 判断头
							if (readlist == null
									&& (bytesToRecv[0] & 0xff) == 0x55) {
								readlist = new ArrayList<Byte>();
							}
						}
						// 第二次
						if (readlist != null && readlist.size() == 1) {
							if (!((bytesToRecv[0] & 0xff) == 0xaa)) {

								// 判断头
								readlist = null;
								readlistTcount = 0;
							}
						}// 如果头是正确的话或者接着接收未接收完的数据
						if (readlist != null) {
							for (int i = 0; i < bytesToRecv.length; i++) {
								readlist.add(bytesToRecv[i]);
							}
							// 第三次跳过，第四次第五次获取长度
							if (readlist != null && readlist.size() >= 5
									&& readlistTcount == 0) {
								String a = Integer
										.toHexString(readlist.get(3) & 0xff);
								String b = Integer
										.toHexString(readlist.get(4) & 0xff);
								if (b.length() < 2) {
									b = "0" + b;
								}
								readlistTcount = Integer.parseInt(a + b, 16) + 7;// 内容长度N
								// +
								// (头2
								// +
								// 随机数1
								// +
								// 长度2
								// +
								// 命令集1
								// +
								// 校验1)
							}

							// 数据接收完整以后
							if (readlistTcount != 0
									&& readlist.size() >= readlistTcount) {
								byte[] bytes = new byte[readlistTcount];
								int tempindex = 0;
								for (Byte b : readlist) {
									if (tempindex == readlistTcount)
										break;

									bytes[tempindex] = b;

									tempindex++;
								}
								readlist = null;
								readlistTcount = 0;
								content = EncodingUtil.bytesToHexString(bytes);
								// 检查数据是否完整
								content = EncodingUtil.checking(content);
								if (content.substring(12, 14).equals("BF")) {
									content = "";
									readlist = null;
									readlistTcount = 0;
									continue;
								} else {
									readlist = null;
									readlistTcount = 0;
									break;
								}

							}
						}

					}
				} else {
					if (x > 0) {
						/*
						 * bytesToRecv = new byte[x];
						 * inputStream.read(bytesToRecv);
						 */
						content = "";
						readlist = null;
						readlistTcount = 0;
					}
					throw new IOException("设备交互超时,请重试!");
				}
			}
			bytesToRecv = null;
			readlist = null;
			readlistTcount = 0;
			if (content == null) {
				throw new NoSuchElementException("报文格式不正确！");
			}
		} catch (Exception e) {
			throw new Exception(e.getMessage());

		}
		return content;
	}

	/**
	 * 读取数据
	 *
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	public String read(String context, int timeOut) throws IOException,
			Exception {
		outputStream.write(EncodingUtil.hex2byte(EncodingUtil.change(context)));
		String content = "";
		int x = 0;
		long time = System.currentTimeMillis();
		while (true) {
			x = inputStream.available(); // 预测缓存区数据长度
			if (System.currentTimeMillis() - time <= timeOut) {
				if (x > 0) {
					bytesToRecv = new byte[x];
					inputStream.read(bytesToRecv);
					content += EncodingUtil.bytesToHexString(bytesToRecv);
					if (checkFF(content)) {
						break;
					}
				}
			} else {
				return null;
			}
		}
		bytesToRecv = null;
		return content;
	}

	private List<Byte> readlist_ = null;

	private long time_ = 0;

	/**
	 * 接收设备指令 (BF指令是设备发送的)
	 *
	 * @throws IOException
	 */
	public String receive() throws IOException, Exception {
		int x = 0;
		String data = "";
		x = inputStream.available(); // 预测缓存区数据长度
		if (x > 0) {
			bytesToRecv = new byte[x];
			inputStream.read(bytesToRecv);
			data = EncodingUtil.checking(EncodingUtil
					.bytesToHexString(bytesToRecv));
			Log.e("接收到的按键消息:", data + "");
			if (data == null) {

			} else {
				if (data.length() >= 14 && !data.substring(12, 14).equals("BF")) {
					return null;
				} else {
					return data;
				}
			}
			bytesToRecv = null;
			return data;
		} else {
			bytesToRecv = null;
			return null;
		}

	}

	/**
	 * 发送延时数据（只发送不接收）
	 *
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public void sendDelayedDate(String context) throws IOException,
			InterruptedException {
		outputStream.write(EncodingUtil.hex2byte(EncodingUtil.change(context)));
	}

	/**
	 * 清空串口数据（接收舍弃）
	 *
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public void receiveDelayedDate() throws IOException, InterruptedException {
		int x;
		String content = "";
		String data = "";
		time = System.currentTimeMillis() + 10000;
		while (true) {
			x = inputStream.available(); // 预测缓存区数据长度
			if (System.currentTimeMillis() <= time) {
				if (x > 0) {
					bytesToRecv = new byte[x];
					inputStream.read(bytesToRecv);
					content += EncodingUtil.bytesToHexString(bytesToRecv);
					try {
						// 检查数据是否完整
						data = EncodingUtil.checking(content);
						Log.e("接收穿插：", data);
						break;
					} catch (Exception e) {
						data += content;
					}
				}
			} else {
				if (x > 0) {
					bytesToRecv = new byte[x];
					inputStream.read(bytesToRecv);
					break;
				} else {
					break;
				}
			}
		}
		bytesToRecv = null;
	}

	public boolean checkFF(String str) {
		if (str != null) {
			int x = str.indexOf("FF");
			int y = str.lastIndexOf("FF");
			if ((x >= 0 && y > 4) && (x % 2 == 0 && y % 2 == 0)) {
				return true;
			}
		}
		return false;
	}
}
